package org.maven.repositorysnapshot;
/**********************************************************************
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Contributors:

**********************************************************************/
import org.maven.dependencybrowser.gui.ProgressMeter;
import org.maven.dependencybrowser.implementations.zip.ZipFileRepository;
import org.maven.dependencybrowser.implementations.zip.ZipFileWorkspace;

import java.io.*;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipOutputStream;

public class RepositorySnapshot
{

    private final File snapshotFile;
    private final File repositoryRoot;
    private final File workspace;

    public RepositorySnapshot(File repositoryRoot, File snapshotFile, File workspace)
    {
        this.repositoryRoot = repositoryRoot;
        this.snapshotFile = snapshotFile;
        this.workspace = workspace;
    }

    public void createSnapshot(ProgressMeter progressMeter) throws ZipException, IOException
    {
        snapshotFile.delete();
        snapshotFile.getParentFile().mkdirs();
        snapshotFile.createNewFile();
        ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(snapshotFile)));
        out.setLevel(Deflater.BEST_COMPRESSION);
        out.setMethod(ZipOutputStream.DEFLATED);

        HierarchyFilter workspaceFilter = new HierarchyFilter()
        {

            public boolean includeDirectory(File directory) throws IOException
            {
                if (directory.getName().equals(".metadata"))
                {
                    return false;
                }
                if (directory.getCanonicalPath().equals(repositoryRoot.getCanonicalPath()))
                {
                    return false;
                }
                return true;
            }

        };

        addHeirarchy(workspace, out, ZipFileWorkspace.PREFIX_WORKSPACE, workspaceFilter, progressMeter);

        HierarchyFilter repositoryFilter = new HierarchyFilter()
        {

            public boolean includeFile(File file) throws IOException
            {
                if (!file.getName().endsWith(".pom"))
                {
                    // excude non-pom files
                    return false;
                }
                if (file.getName().matches("^.*-\\d{8}\\.\\d{6}-\\d+\\.pom$"))
                {
                    // exclude snapshot builds
                    return false;
                }
                return true;
            }

        };

        addHeirarchy(repositoryRoot, out, ZipFileRepository.PREFIX_REPOSITORY, repositoryFilter, progressMeter);
        out.close();
    }

    private void addHeirarchy(File directory, ZipOutputStream out, String repoPath, HierarchyFilter filter, ProgressMeter progressMeter) throws IOException
    {
        File[] files = directory.listFiles();
        for (int i = 0; i < files.length; i++)
        {
            File file = files[i];
            if (file.isDirectory() && filter.includeDirectory(file))
            {
                progressMeter.scanning(file);
                addHeirarchy(file, out, repoPath + "/" + file.getName(), filter, progressMeter);
            }
            else
            {
                if (filter.includeFile(file))
                {
                    progressMeter.adding(file);
                    addEntry(file, repoPath + "/" + file.getName(), out);
                }
            }
        }
    }

    private class HierarchyFilter
    {

        public boolean includeFile(File file) throws IOException
        {
            return file.getName().equals("pom.xml");
        }

        public boolean includeDirectory(File directory) throws IOException
        {
            return true;
        }
    }

    private void addEntry(File target, String repoPath, ZipOutputStream out) throws IOException
    {
        ZipEntry entry = new ZipEntry(repoPath);
        int fileLength = (int) target.length();
        FileInputStream fis = new FileInputStream(target);
        byte[] wholeFile = new byte[fileLength];
        fis.read(wholeFile, 0, fileLength);
        fis.close();
        out.putNextEntry(entry);
        out.write(wholeFile, 0, fileLength);
        out.closeEntry();
    }

}
